home *** CD-ROM | disk | FTP | other *** search
- {$R-,B-,S-,I+,N-}
-
- program TextToSpeech (Input, Output);
-
- { ***** Preliminary version ***** }
- { Author: Ron Schuster 76666,2322 }
-
- type
- CharSet = set of 'A'..'Z';
-
- const
- Vowels : CharSet = ['A','E','I','O','U','Y'];
- FrontVowels : CharSet = ['E','I','Y'];
- Consonants : CharSet = ['B','C','D','F','G','H','J','K','L','M','N',
- 'P','Q','R','S','T','V','W','X','Z'];
- VoicedConsonants : CharSet = ['B','D','G','J','L','M','N','R','V','W','Z'];
- Sibilants : CharSet = ['S','C','G','Z','X','J'];
- UruleConsonants : CharSet = ['T','S','R','D','L','Z','N','J'];
- Set_CS : CharSet = ['C','S'];
- Set_CST : CharSet = ['C','S','T'];
- Set_AERU : CharSet = ['A','E','R','U'];
- Set_ER : CharSet = ['E','R'];
- Set_GK : CharSet = ['G','K'];
- Set_EIORU : CharSet = ['E','I','O','R','U'];
- Set_ERU : CharSet = ['E','R','U'];
- MaxContextLen = 7;
- MaxTransLen = 35;
- MaxRuleCount = 600;
- var
- Rule : array [1..MaxRuleCount] of record
- LeftContext : string[MaxContextLen];
- CenterContext : string[MaxContextLen];
- RightContext : string[MaxContextLen];
- Translation : string[MaxTransLen];
- end;
- RuleIndex : array [' '..'~'] of Integer; { points to the first rule that
- handles each character }
- InStr, OutStr : string;
- RuleCount, Code,
- InPtr, RulePtr : Integer;
-
- function Match (Context : Char; var InPtr : Integer; Direction : Integer) : Boolean;
- var
- Temp : string[4];
- begin
- case Context of
- '!': case InStr[InPtr] of { Non-alphabetic }
- 'A'..'Z','''': Match := False;
- else Match := True;
- end;
- '#': begin { One or more vowels }
- Match := False;
- while InStr[InPtr] in Vowels do begin
- InPtr := InPtr + Direction;
- Match := True;
- end;
- InPtr := InPtr - Direction;
- end;
- '.': Match := InStr[InPtr] in VoicedConsonants; { A voiced consonant }
- '%': begin { A suffix }
- Match := True;
- Temp := Copy(InStr, InPtr, 3);
- if Length(Temp) = 3 then
- if Temp <> 'ING' then
- if Temp <> 'ELY' then
- Dec(Temp[0]);
- if Length(Temp) = 2 then
- if Temp <> 'ES' then
- if Temp <> 'ER' then
- if Temp <> 'ED' then
- Dec(Temp[0]);
- if Length(Temp) = 1 then
- if Temp <> 'E' then
- Match := False;
- Inc (InPtr, Pred(Length(Temp)));
- end;
- '&': if InStr[InPtr] in Sibilants then { Sibilants }
- Match := True
- else
- Match := (InStr[InPtr] = 'H') and (InStr[InPtr-1] in Set_CS);
- '@': if InStr[InPtr] in UruleConsonants then { A consonant influen- }
- Match := True { cing the sound of }
- else { following 'U' }
- Match := (InStr[InPtr] = 'H') and (InStr[InPtr-1] in Set_CST);
- '^': Match := InStr[InPtr] in Consonants; { One consonant }
- '+': Match := InStr[InPtr] in FrontVowels; { A front vowel }
- ':': begin { Zero or more }
- while InStr[InPtr] in Consonants do { consonants }
- InPtr := InPtr + Direction;
- Match := True;
- InPtr := InPtr - Direction;
- end;
- '$': Match := InStr[InPtr] in Vowels; { One vowel }
- else Match := InStr[InPtr] = Context; { Literal }
- end;
- end;
-
- procedure TestRules;
- var
- I,J : Integer;
- OK : Boolean;
- begin
- RulePtr := RuleIndex[InStr[InPtr]];
- repeat
- with Rule[RulePtr] do begin
- OK := Copy(InStr,InPtr,Length(CenterContext)) = CenterContext;
- if OK then begin
- I := Length(LeftContext);
- J := InPtr;
- while OK and (I > 0) do begin
- Dec(J);
- OK := Match (LeftContext[I], J, -1);
- Dec(I);
- end;
- end;
- if OK then begin
- I := 1;
- J := InPtr + Length(CenterContext);
- while OK and (I <= Length(RightContext)) do begin
- OK := Match (RightContext[I], J, 1);
- Inc(I);
- Inc(J);
- end;
- end;
- end; { with Rule[RulePtr] }
- if not OK then
- Inc(RulePtr);
- until OK or (RulePtr > RuleCount);
- end;
-
- procedure PrepareInputString;
- var
- I : Integer;
- begin
- for I := 1 to Length(InStr) do
- InStr[I] := UpCase(InStr[I]);
- InStr := ' '+ InStr + ' ';
- end;
-
- {$R+}
- procedure ReadRules;
- var
- RuleFile : text;
- C : Char;
- begin
- {$I-}
- Assign (RuleFile, 'RULES.DAT');
- Reset (RuleFile);
- {$I+}
- if IOresult <> 0 then begin
- Writeln ('Could not open RULES.DAT');
- Halt(1);
- end;
- RuleCount := 0;
- for C := ' ' to '~' do
- RuleIndex[C] := 0;
- while not EOF(RuleFile) do begin
- ReadLn (RuleFile, InStr);
- RuleCount := RuleCount + 1;
- with Rule[RuleCount] do begin
- LeftContext := Copy (InStr, 1, Pos('[',InStr) - 1);
- Delete (InStr, 1, Length(LeftContext) + 1);
- if InStr[1] = ']' then
- CenterContext := ']'
- else
- CenterContext := Copy (InStr, 1, Pos(']',InStr) - 1);
- Delete (InStr, 1, Length(CenterContext) + 1);
- RightContext := Copy (InStr, 1, Pos('=',InStr) - 1);
- Delete (InStr, 1, Length(RightContext) + 1);
- Translation := InStr;
- C := CenterContext[1];
- if RuleIndex[C] = 0 then
- RuleIndex[C] := RuleCount;
- end;
- end;
- Rule[RuleCount + 1].Translation := 'ERROR';
- end;
- {$R-}
-
- procedure WriteOutput;
- begin
- with Rule[RulePtr] do begin
- OutStr := OutStr + Translation + ' ';
- if Length(OutStr) > 80 then begin
- Writeln (OutStr);
- OutStr := '';
- end;
- Inc (InPtr, Length(CenterContext));
- end;
- end;
-
- procedure ProcessInputFile;
- begin
- while not EOF(Input) do begin
- OutStr := '';
- Readln (Input, InStr);
- PrepareInputString;
- InPtr := 2;
- while InPtr < Length(InStr) do begin
- case InStr[InPtr] of
- ' '..'~': if RuleIndex[InStr[InPtr]] = 0 then
- Inc(InPtr)
- else begin
- TestRules;
- WriteOutput;
- end;
- else Inc(InPtr);
- end;
- end;
- if Length(OutStr) > 0 then
- Writeln (OutStr);
- end;
- Close(Output);
- end;
-
- { main program }
- begin
- ReadRules;
- ProcessInputFile;
- end.